home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / Newswatcher 2.0b22 / NW Source / Source / dnr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-05  |  15.1 KB  |  550 lines  |  [TEXT/MMCC]

  1. /*
  2.     DNR.c - DNR library for MPW
  3.  
  4.     © Copyright 1988 by Apple Computer.  All rights reserved
  5.     
  6. */
  7.  
  8. /*----------------------------------------------------------
  9.  
  10.     DANGER WILL ROBINSON!!!!
  11.     
  12.     This file started life on the CW DR/3 CD. It was crap.
  13.     I had to hack it to death to get it to work.
  14.     
  15. -----------------------------------------------------------*/
  16.  
  17. #pragma require_prototypes off
  18.  
  19. #define MPW3.0
  20.  
  21. #include <OSUtils.h>
  22. #include <Errors.h>
  23. #include <Files.h>
  24. #include <Resources.h>
  25. #include <Memory.h>
  26. #include <Traps.h>
  27. #include <GestaltEqu.h>
  28. #include <Folders.h>
  29. #include <MixedMode.h>
  30.  
  31. #include <AddressXlation.h>                                        
  32.  
  33.  
  34.  
  35.  
  36. #define OPENRESOLVER    1
  37. #define CLOSERESOLVER    2
  38. #define STRTOADDR        3
  39. #define    ADDRTOSTR        4
  40. #define    ENUMCACHE        5
  41. #define ADDRTONAME        6
  42. #define    HINFO            7
  43. #define MXINFO            8
  44.  
  45. Handle                 codeHndl = nil;
  46. UniversalProcPtr    dnr = nil;
  47.  
  48.  
  49. static TrapType GetTrapType (unsigned long theTrap)
  50. {
  51.     if (BitAnd(theTrap, 0x0800) > 0)
  52.         return(ToolTrap);
  53.     else
  54.         return(OSTrap);
  55. }
  56.     
  57. static Boolean TrapAvailable (unsigned long trap)
  58. {
  59. TrapType trapType = ToolTrap;
  60. unsigned long numToolBoxTraps;
  61.  
  62.     if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
  63.         numToolBoxTraps = 0x200;
  64.     else
  65.         numToolBoxTraps = 0x400;
  66.  
  67.     trapType = GetTrapType(trap);
  68.     if (trapType == ToolTrap) {
  69.         trap = BitAnd(trap, 0x07FF);
  70.         if (trap >= numToolBoxTraps)
  71.             trap = _Unimplemented;
  72.         }
  73.     return(NGetTrapAddress(trap, trapType) != NGetTrapAddress(_Unimplemented, ToolTrap));
  74.  
  75. }
  76.  
  77. void GetSystemFolder(short *vRefNumP, long *dirIDP)
  78. {
  79.     SysEnvRec info;
  80.     long wdProcID;
  81.     
  82.     SysEnvirons(1, &info);
  83.     if (GetWDInfo(info.sysVRefNum, vRefNumP, dirIDP, &wdProcID) != noErr) {
  84.         *vRefNumP = 0;
  85.         *dirIDP = 0;
  86.         }
  87.     }
  88.  
  89. void GetCPanelFolder(short *vRefNumP, long *dirIDP)
  90. {
  91.     Boolean hasFolderMgr = false;
  92.     long feature;
  93.     
  94.     if (Gestalt(gestaltFindFolderAttr, &feature) == noErr) 
  95.         hasFolderMgr = true;
  96.     if (!hasFolderMgr) {
  97.         GetSystemFolder(vRefNumP, dirIDP);
  98.         return;
  99.         }
  100.     else {
  101.         if (FindFolder(kOnSystemDisk, kControlPanelFolderType, kDontCreateFolder, vRefNumP, dirIDP) != noErr) {
  102.             *vRefNumP = 0;
  103.             *dirIDP = 0;
  104.             }
  105.         }
  106.     }
  107.     
  108. /* SearchFolderForDNRP is called to search a folder for files that might 
  109.     contain the 'dnrp' resource */
  110. short SearchFolderForDNRP(long targetType, long targetCreator, short vRefNum, long dirID)
  111. {
  112.     HParamBlockRec fi;
  113.     Str255 filename;
  114.     short refnum;
  115.     
  116.     fi.fileParam.ioCompletion = nil;
  117.     fi.fileParam.ioNamePtr = filename;
  118.     fi.fileParam.ioVRefNum = vRefNum;
  119.     fi.fileParam.ioDirID = dirID;
  120.     fi.fileParam.ioFDirIndex = 1;
  121.     
  122.     while (PBHGetFInfo(&fi, false) == noErr) {
  123.         /* scan system folder for driver resource files of specific type & creator */
  124.         if (fi.fileParam.ioFlFndrInfo.fdType == targetType &&
  125.             fi.fileParam.ioFlFndrInfo.fdCreator == targetCreator) {
  126.             /* found the MacTCP driver file? */
  127.             refnum = HOpenResFile(vRefNum, dirID, filename, fsRdPerm);
  128.             if (GetIndResource('dnrp', 1) == NULL)
  129.                 CloseResFile(refnum);
  130.             else
  131.                 return refnum;
  132.             }
  133.         /* check next file in system folder */
  134.         fi.fileParam.ioFDirIndex++;
  135.         fi.fileParam.ioDirID = dirID;    /* PBHGetFInfo() clobbers ioDirID */
  136.         }
  137.     return(-1);
  138.     }    
  139.  
  140.  
  141.  
  142. /* OpenOurRF is called to open the MacTCP driver resources */
  143.  
  144. short OpenOurRF()
  145. {
  146.     short refnum;
  147.     short vRefNum;
  148.     long dirID;
  149.     
  150.     /* first search Control Panels for MacTCP 1.1 */
  151.     GetCPanelFolder(&vRefNum, &dirID);
  152.     refnum = SearchFolderForDNRP('cdev', 'ztcp', vRefNum, dirID);
  153.     if (refnum != -1) return(refnum);
  154.         
  155.     /* next search System Folder for MacTCP 1.0.x */
  156.     GetSystemFolder(&vRefNum, &dirID);
  157.     refnum = SearchFolderForDNRP('cdev', 'mtcp', vRefNum, dirID);
  158.     if (refnum != -1) return(refnum);
  159.         
  160.     /* finally, search Control Panels for MacTCP 1.0.x */
  161.     GetCPanelFolder(&vRefNum, &dirID);
  162.     refnum = SearchFolderForDNRP('cdev', 'mtcp', vRefNum, dirID);
  163.     if (refnum != -1) return(refnum);
  164.         
  165.     return -1;
  166.     }    
  167.  
  168.  
  169.  
  170.  
  171. typedef OSErr (*OpenResolverProcPtr)(long selector, char* fileName);
  172.  
  173. enum {
  174.     uppOpenResolverProcInfo = kCStackBased
  175.          | RESULT_SIZE(SIZE_CODE(sizeof(short)))
  176.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
  177.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char *)))
  178. };
  179.  
  180. #if USESROUTINEDESCRIPTORS
  181. typedef UniversalProcPtr OpenResolverUPP;
  182.  
  183. #define    NewOpenResolverProc(userRoutine)                        \
  184.         (OpenResolverUPP) NewRoutineDescriptor(userRoutine, uppOpenResolverProcInfo, GetCurrentISA())
  185. #define    CallOpenResolverProc(userRoutine, selector, filename)    \
  186.         CallUniversalProc(userRoutine, uppOpenResolverProcInfo, selector, filename)
  187. #else
  188. typedef OpenResolverProcPtr OpenResolverUPP;
  189.  
  190. #define    NewOpenResolverProc(userRoutine)                    \
  191.         (OpenResolverUPP)(userRoutine)
  192. #define    CallOpenResolverProc(userRoutine, selector, filename)    \
  193.         (*(OpenResolverProcPtr)userRoutine)(selector, filename)
  194. #endif
  195.  
  196.  
  197.  
  198. OSErr OpenResolver(fileName)
  199. char *fileName;
  200. {
  201.     short             refnum;
  202.     OSErr             rc;
  203.     
  204.     if (dnr != nil)
  205.         /* resolver already loaded in */
  206.         return(noErr);
  207.         
  208.     /* open the MacTCP driver to get DNR resources. Search for it based on
  209.        creator & type rather than simply file name */    
  210.     refnum = OpenOurRF();
  211.  
  212.     /* ignore failures since the resource may have been installed in the 
  213.        System file if running on a Mac 512Ke */
  214.        
  215.     /* load in the DNR resource package */
  216.     codeHndl = GetIndResource('dnrp', 1);
  217.     if (codeHndl == nil) {
  218.         /* can't open DNR */
  219.         return(ResError());
  220.     }
  221.     
  222.     DetachResource(codeHndl);
  223.     if (refnum != -1) {
  224.         CloseResFile(refnum);
  225.     }
  226.         
  227.     /* lock the DNR resource since it cannot be reloated while opened */
  228.     HLock(codeHndl);
  229.     dnr = (UniversalProcPtr) *codeHndl;
  230.     
  231.     /* call open resolver */
  232.     rc = CallOpenResolverProc(dnr, OPENRESOLVER, fileName);
  233.     if (rc != noErr) {
  234.         /* problem with open resolver, flush it */
  235.         HUnlock(codeHndl);
  236.         DisposeHandle(codeHndl);
  237.         dnr = nil;
  238.     }
  239.     return(rc);
  240. }
  241.  
  242.  
  243.  
  244. typedef OSErr (*CloseResolverProcPtr)(long selector);
  245.  
  246. enum {
  247.     uppCloseResolverProcInfo = kCStackBased
  248.          | RESULT_SIZE(SIZE_CODE(sizeof(short)))
  249.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
  250. };
  251.  
  252. #if USESROUTINEDESCRIPTORS
  253. typedef UniversalProcPtr CloseResolverUPP;
  254.  
  255. #define    NewCloseResolverProc(userRoutine)                        \
  256.         (CloseResolverUPP) NewRoutineDescriptor(userRoutine, uppCloseResolverProcInfo, GetCurrentISA())
  257. #define    CallCloseResolverProc(userRoutine, selector)    \
  258.         CallUniversalProc(userRoutine, uppCloseResolverProcInfo, selector)
  259. #else
  260. typedef CloseResolverProcPtr CloseResolverUPP;
  261.  
  262. #define    NewCloseResolverProc(userRoutine)                         \
  263.         (CloseResolverUPP)(userRoutine)
  264. #define    CallCloseResolverProc(userRoutine, selector)    \
  265.         (*(CloseResolverProcPtr)userRoutine)(selector)
  266. #endif
  267.  
  268.  
  269.  
  270. OSErr CloseResolver()
  271. {
  272.     if (dnr == nil)
  273.         /* resolver not loaded error */
  274.         return(notOpenErr);
  275.         
  276.     /* call close resolver */
  277.     CallCloseResolverProc(dnr, CLOSERESOLVER);
  278.  
  279.     /* release the DNR resource package */
  280.     HUnlock(codeHndl);
  281.     DisposeHandle(codeHndl);
  282.     dnr = nil;
  283.     return(noErr);
  284. }
  285.  
  286.  
  287.  
  288.  
  289. typedef OSErr (*StrToAddrProcPtr)(long selector, char* hostName, struct hostInfo* rtnStruct,
  290.                                     long resultProc, char* userData);
  291.                                     
  292. enum {
  293.     uppStrToAddrProcInfo = kCStackBased
  294.          | RESULT_SIZE(SIZE_CODE(sizeof(short)))
  295.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
  296.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char *)))
  297.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(struct hostInfo *)))
  298.          | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
  299.          | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(char *)))
  300. };
  301.  
  302. #if USESROUTINEDESCRIPTORS
  303. typedef UniversalProcPtr StrToAddrUPP;
  304.  
  305. #define    NewStrToAddrProc(userRoutine)                        \
  306.         (StrToAddrUPP) NewRoutineDescriptor(userRoutine, uppStrToAddrProcInfo, GetCurrentISA())
  307. #define    CallStrToAddrProc(userRoutine, selector, hostName, rtnStruct, resultProc, userData)    \
  308.         CallUniversalProc(userRoutine, uppStrToAddrProcInfo, selector, hostName, rtnStruct, resultProc, userData)
  309. #else
  310. typedef StrToAddrProcPtr StrToAddrUPP;
  311.  
  312. #define    NewStrToAddrProc(userRoutine)                        \
  313.         (StrToAddrUPP)(userRoutine)
  314. #define    CallStrToAddrProc(userRoutine, selector, hostName, rtnStruct, resultProc, userData)    \
  315.         (*(StrToAddrProcPtr)userRoutine)(selector, hostName, rtnStruct, resultProc, userData)
  316. #endif
  317.  
  318.  
  319.  
  320. OSErr StrToAddr(hostName, rtnStruct, resultproc, userDataPtr)
  321. char *hostName;
  322. struct hostInfo *rtnStruct;
  323. long resultproc;
  324. char *userDataPtr;
  325. {
  326.     if (dnr == nil)
  327.         /* resolver not loaded error */
  328.         return(notOpenErr);
  329.         
  330.     return(CallStrToAddrProc(dnr, STRTOADDR, hostName, rtnStruct, resultproc, userDataPtr));
  331. }
  332.  
  333.  
  334. typedef OSErr (*AddrToStrProcPtr)(long selector, long address, char* hostName);
  335.  
  336. enum {
  337.     uppAddrToStrProcInfo = kCStackBased
  338.          | RESULT_SIZE(SIZE_CODE(sizeof(short)))
  339.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
  340.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(unsigned long)))
  341.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(char *)))
  342. };
  343.  
  344. #if USESROUTINEDESCRIPTORS
  345. typedef UniversalProcPtr AddrToStrUPP;
  346.  
  347. #define    NewAddrToStrProc(userRoutine)                        \
  348.         (AddrToStrUPP) NewRoutineDescriptor(userRoutine, uppAddrToStrProcInfo, GetCurrentISA())
  349. #define    CallAddrToStrProc(userRoutine, selector, address, hostName)    \
  350.         CallUniversalProc(userRoutine, uppAddrToStrProcInfo, selector, address, hostName)
  351. #else
  352. typedef AddrToStrProcPtr AddrToStrUPP;
  353.  
  354. #define    NewAddrToStrProc(userRoutine)                        \
  355.         (AddrToStrUPP)(userRoutine)
  356. #define    CallAddrToStrProc(userRoutine, selector, address, hostName)    \
  357.         (*(AddrToStrProcPtr)userRoutine)(selector, address, hostName)
  358. #endif
  359.  
  360.     
  361. OSErr AddrToStr(addr, addrStr)
  362. unsigned long addr;
  363. char *addrStr;                                    
  364. {
  365.     if (dnr == nil)
  366.         /* resolver not loaded error */
  367.         return(notOpenErr);
  368.         
  369.     CallAddrToStrProc(dnr, ADDRTOSTR, addr, addrStr);
  370.  
  371.     return(noErr);
  372. }
  373.  
  374.  
  375.  
  376. typedef OSErr (*EnumCacheProcPtr)(long selector, long result, char* userData);
  377.  
  378. enum {
  379.     uppEnumCacheProcInfo = kCStackBased
  380.          | RESULT_SIZE(SIZE_CODE(sizeof(short)))
  381.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
  382.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long)))
  383.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(char *)))
  384. };
  385.  
  386. #if USESROUTINEDESCRIPTORS
  387. typedef UniversalProcPtr EnumCacheUPP;
  388.  
  389. #define    NewEnumCacheProc(userRoutine)                        \
  390.         (EnumCacheUPP) NewRoutineDescriptor(userRoutine, uppEnumCacheProcInfo, GetCurrentISA())
  391. #define    CallEnumCacheProc(userRoutine, selector, result, userData)    \
  392.         CallUniversalProc(userRoutine, uppEnumCacheProcInfo, selector, result, userData)
  393. #else
  394. typedef EnumCacheProcPtr EnumCacheUPP;
  395.  
  396. #define    NewEnumCacheProc(userRoutine)                        \
  397.         (EnumCacheUPP)(userRoutine)
  398. #define    CallEnumCacheProc(userRoutine, selector, result, userData)    \
  399.         (*(EnumCacheProcPtr)userRoutine)(selector, result, userData)
  400. #endif
  401.  
  402.  
  403.     
  404. OSErr EnumCache(resultproc, userDataPtr)
  405. long resultproc;
  406. char *userDataPtr;
  407. {
  408.     if (dnr == nil)
  409.         /* resolver not loaded error */
  410.         return(notOpenErr);
  411.         
  412.     return(CallEnumCacheProc(dnr, ENUMCACHE, resultproc, userDataPtr));
  413. }
  414.  
  415.  
  416.  
  417. typedef OSErr (*AddrToNameProcPtr)(long selector, unsigned long addr, struct hostInfo* rtnStruct,
  418.                                     long resultProc, char* userData);
  419.  
  420. enum {
  421.     uppAddrToNameProcInfo = kCStackBased
  422.          | RESULT_SIZE(SIZE_CODE(sizeof(short)))
  423.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
  424.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(unsigned long)))
  425.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(struct hostInfo *)))
  426.          | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
  427.          | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(char *)))
  428.  
  429. };
  430.  
  431. #if USESROUTINEDESCRIPTORS
  432. typedef UniversalProcPtr AddrToNameUPP;
  433.  
  434. #define    NewAddrToNameProc(userRoutine)                        \
  435.         (AddrToNameUPP) NewRoutineDescriptor(userRoutine, uppAddrToNameProcInfo, GetCurrentISA())
  436. #define    CallAddrToNameProc(userRoutine, selector, addr, rtnStruct, resultProc, userData)    \
  437.         CallUniversalProc(userRoutine, uppAddrToNameProcInfo, selector, addr, rtnStruct, resultProc, userData)
  438. #else
  439. typedef AddrToNameProcPtr AddrToNameUPP;
  440.  
  441. #define    NewAddrToNameProc(userRoutine)                        \
  442.         (AddrToNameUPP)(userRoutine)
  443. #define    CallAddrToNameProc(userRoutine, selector, addr, rtnStruct, resultProc, userData)    \
  444.         (*(AddrToNameProcPtr)userRoutine)(selector, addr, rtnStruct, resultProc, userData)
  445. #endif
  446.  
  447.     
  448.     
  449. OSErr AddrToName(addr, rtnStruct, resultproc, userDataPtr)
  450. unsigned long addr;
  451. struct hostInfo *rtnStruct;
  452. long resultproc;
  453. char *userDataPtr;                                    
  454. {
  455.     if (dnr == nil)
  456.         /* resolver not loaded error */
  457.         return(notOpenErr);
  458.         
  459.     return(CallAddrToNameProc(dnr, ADDRTONAME, addr, rtnStruct, resultproc, userDataPtr));
  460. }
  461.  
  462.  
  463. typedef OSErr (*HInfoProcPtr)(long selector, char* hostName, struct returnRec* returnRecPtr,
  464.                                 long resultProc, char* userData);
  465.  
  466. enum {
  467.     uppHInfoProcInfo = kCStackBased
  468.          | RESULT_SIZE(SIZE_CODE(sizeof(short)))
  469.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
  470.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char *)))
  471.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(struct returnRec *)))
  472.          | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
  473.          | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(char *)))
  474.  
  475. };
  476.  
  477. #if USESROUTINEDESCRIPTORS
  478. typedef UniversalProcPtr HInfoUPP;
  479.  
  480. #define    NewHInfoProc(userRoutine)                        \
  481.         (HInfoUPP) NewRoutineDescriptor(userRoutine, uppHInfoProcInfo, GetCurrentISA())
  482. #define    CallHInfoProc(userRoutine, selector, hostName, returnRecPtr, resultProc, userData)    \
  483.         CallUniversalProc(userRoutine, uppHInfoProcInfo, selector, hostName, returnRecPtr, resultProc, userData)
  484. #else
  485. typedef HInfoProcPtr HInfoUPP;
  486.  
  487. #define    NewHInfoProc(userRoutine)                        \
  488.         (HInfoUPP)(userRoutine)
  489. #define    CallHInfoProc(userRoutine, selector, hostName, returnRecPtr, resultProc, userData)    \
  490.         (*(HInfoProcPtr)userRoutine)(selector, hostName, returnRecPtr, resultProc, userData)
  491. #endif
  492.  
  493. extern OSErr HInfo(hostName, returnRecPtr, resultProc, userDataPtr)
  494. char *hostName;
  495. struct returnRec *returnRecPtr;
  496. long resultProc;
  497. char *userDataPtr;
  498. {
  499.     if (dnr == nil)
  500.         /* resolver not loaded error */
  501.         return(notOpenErr);
  502.         
  503.     return(CallHInfoProc(dnr, HINFO, hostName, returnRecPtr, resultProc, userDataPtr));
  504. }
  505.  
  506.  
  507.  
  508. typedef OSErr (*MXInfoProcPtr)(long selector, char* hostName, struct returnRec* returnRecPtr,
  509.                                 long resultProc, char* userData);
  510.  
  511. enum {
  512.     uppMXInfoProcInfo = kCStackBased
  513.          | RESULT_SIZE(SIZE_CODE(sizeof(short)))
  514.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
  515.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char *)))
  516.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(struct returnRec *)))
  517.          | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
  518.          | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(char *)))
  519.  
  520. };
  521.  
  522. #if USESROUTINEDESCRIPTORS
  523. typedef UniversalProcPtr MXInfoUPP;
  524.  
  525. #define    NewMXInfoProc(userRoutine)                        \
  526.         (MXInfoUPP) NewRoutineDescriptor(userRoutine, uppMXInfoProcInfo, GetCurrentISA())
  527. #define    CallMXInfoProc(userRoutine, selector, hostName, returnRecPtr, resultProc, userData)    \
  528.         CallUniversalProc(userRoutine, selector, hostName, returnRecPtr, resultProc, userData)
  529. #else
  530. typedef MXInfoProcPtr MXInfoUPP;
  531.  
  532. #define    NewMXInfoProc(userRoutine)                        \
  533.         (MXInfoUPP)(userRoutine)
  534. #define    CallMXInfoProc(userRoutine, selector, hostName, returnRecPtr, resultProc, userData)    \
  535.         (*(MXInfoProcPtr)userRoutine)(selector, hostName, returnRecPtr, resultProc, userData)
  536. #endif
  537.     
  538.     
  539. extern OSErr MXInfo(hostName, returnRecPtr, resultProc, userDataPtr)
  540. char *hostName;
  541. struct returnRec *returnRecPtr;
  542. long resultProc;
  543. char *userDataPtr;
  544. {
  545.     if (dnr == nil)
  546.         /* resolver not loaded error */
  547.         return(notOpenErr);
  548.         
  549.     return(CallMXInfoProc(dnr, MXINFO, hostName, returnRecPtr, resultProc, userDataPtr));
  550. }